﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;

namespace ZQNB.Common.NHExtensions
{
    public static class NbSessionFactoryForWeb
    {
        /// <summary>
        /// 全局统一SF初始化，对于一个ASP.NET MVC项目，一般在Application_Start方法中调用。
        /// 一次调用初始化一个SessionFactory
        /// </summary>
        /// <param name="dbCfg">NH数据库配置</param>
        /// <param name="mappings">NH映射配置</param>
        /// <param name="buildSchema">是否自动创建或重新创建数据库表，默认不创建</param>
        /// <param name="sfName">SF名，标识不同的SF, 默认为空串</param>
        public static void InitSessionFactory(IPersistenceConfigurer dbCfg,
                                            Action<MappingConfiguration> mappings,
                                            bool buildSchema = false,
                                            string sfName = "")
        {
            if (_sessionFactories.ContainsKey(sfName))
                throw new ArgumentException("Duplicate Session Factory name");

            var cfg = Fluently.Configure()
                        .Database(dbCfg)
                        .Mappings(mappings)
                        .ExposeConfiguration(c => c.SetProperty("current_session_context_class", "web"))
                        .BuildConfiguration();

            if (buildSchema)
                BuildSchema(cfg);

            _sessionFactories[sfName] = cfg.BuildSessionFactory();
        }

        /// <summary>
        /// 通过初始化时使用的SF名，用相应的SF来创建NH的ISession，使用者负责ISession的释放
        /// </summary>
        /// <param name="sfName">初始化SF时用的SF名, 默认为空串<</param>
        /// <returns>NH的ISession</returns>
        public static ISession OpenSession(string sfName = "")
        {
            return _sessionFactories[sfName].OpenSession();
        }

        public static ISessionFactory SessionFactory(string sfName = "")
        {
            return _sessionFactories[sfName];
        }

        private static void BuildSchema(Configuration configuration)
        {
            new SchemaExport(configuration).Execute(true, true, false);
        }

        private static readonly Dictionary<string, ISessionFactory> _sessionFactories = new Dictionary<string, ISessionFactory>();
    }
}
